package com.ruoyi.qywx.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.constant.ErrorConstants;
import com.ruoyi.common.core.cache.Meta;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.CollectionUtils;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.common.utils.StrUtils;
import com.ruoyi.qywx.entity.ContactWayEntity;
import com.ruoyi.qywx.entity.QyWelcomeTemplate;
import com.ruoyi.qywx.getway.api.ContactWayApi;
import com.ruoyi.qywx.getway.entity.QyWelcome;
import com.ruoyi.qywx.getway.keys.QywxKey;
import com.ruoyi.qywx.getway.request.TxResponse;
import com.ruoyi.qywx.mapper.ContactWayMapper;
import com.ruoyi.qywx.model.vo.*;
import com.ruoyi.qywx.service.inters.ContactService;
import com.ruoyi.qywx.service.inters.ContactTagServic;
import com.ruoyi.qywx.service.inters.ContactWayService;
import com.ruoyi.qywx.service.inters.WelcomeService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author : hcl
 * @Date : 2023/8/2
 */
@Service
public class ContactWayServiceImpl implements ContactWayService {
    @Resource
    private ContactWayMapper contactWayMapper;
    @Autowired
    private WelcomeService welcomeService;
    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    private ContactTagServic tagServic;
    @Autowired
    private ContactService contactService;
    @Autowired
    private RedisCache redisCache;

    @Override
    public ContactWayVo selectContactWayById(Long id, Long teamId) {
        ContactWayEntity way = contactWayMapper.selectOne(new QueryWrapper<ContactWayEntity>()
                .eq("team_id", teamId)
                .eq("id", id));
        if (Objects.isNull(way)) return null;
        SysUser sysUser = iSysUserService.selectUserById(way.getCreator());

        Map<String, String> userMaps = contactService.contactNamesMap(
                CollectionUtils.toStrList(way.getUsers()),
                teamId
        );
        Map<Long, String> tagMap = tagServic.tagsTurnNameMap(
                CollectionUtils.toLongList(way.getTags()),
                teamId
        );
        ContactWayVo wayVo = new ContactWayVo();
        ContactWayInfo info = new ContactWayInfo();
        if (NumberUtils.isTrue(way.getWelcomeId())) {
            QyWelcomeTemplate welcom = welcomeService.selectById(way.getWelcomeId());
            if (Objects.nonNull(welcom)) {
                WelcomeVo welcomeVo = new WelcomeVo();
                welcomeVo.editWelcome(welcom);
                wayVo.setWelcome(welcomeVo);
            }
        }
        info.editContactWay(way, sysUser, userMaps, tagMap);
        wayVo.setContactWay(info);
        return wayVo;
    }

    /**
     * 活码列表
     */
    @Override
    public List<ContactWayInfo> selectContactWayList(Long teamId, Long groupId, String keyword) {
        QueryWrapper<ContactWayEntity> query = new QueryWrapper<>();
        query.select("id", "group_id", "title", "users", "tags", "modify_time", "qrcode_url", "creator")
                .eq("team_id", teamId);
        if (NumberUtils.isTrue(groupId)) {
            query.eq("group_id", groupId);
        }
        if (StrUtils.isNotEmpty(keyword)) {
            query.like("title", keyword);
        }
        List<ContactWayEntity> ways = contactWayMapper.selectList(query);
        Set<Long> creatorIds = new HashSet<>(), tagIds = new HashSet<>();
        Set<String> userIds = new HashSet<>();
        for (ContactWayEntity entity : ways) {
            creatorIds.add(entity.getCreator());
            if (StrUtils.isNotEmpty(entity.getTags())) {
                tagIds.addAll(CollectionUtils.toLongList(entity.getTags()));
            }
            userIds.addAll(CollectionUtils.toStrList(entity.getUsers()));
        }
        Map<Long, String> creatorMaps = iSysUserService.findUserNameMaps(creatorIds),
                tagMaps = tagServic.tagsTurnNameMap(tagIds, teamId);
        Map<String, String> userMaps = contactService.contactNamesMap(userIds, teamId);

        return CollectionUtils.isEmpty(ways)
                ? Collections.emptyList()
                : ways.stream().map(e -> {
            List<TagVo> tagVos = CollectionUtils.toLongList(e.getTags()).stream()
                    .filter(tagId -> StrUtils.isNotEmpty(tagMaps.get(tagId)))
                    .map(tag -> new TagVo(tag, tagMaps.get(tag)))
                    .collect(Collectors.toList());
            List<ContactVo> users = CollectionUtils.toStrList(e.getUsers()).stream()
                    .filter(userId -> StrUtils.isNotEmpty(userMaps.get(userId)))
                    .map(userId -> new ContactVo(userId, userMaps.get(userId)))
                    .collect(Collectors.toList());
            ContactWayInfo info = new ContactWayInfo();
            info.setId(e.getId());
            info.setTitle(e.getTitle());
            info.setCreator(creatorMaps.getOrDefault(e.getCreator(), "未知"));
            info.setUsers(users);
            info.setTags(tagVos);
            info.setGroupId(e.getGroupId());
            info.setModifyTime(e.getModifyTime());
            info.setQrcodeUrl(e.getQrcodeUrl());
            return info;
        }).collect(Collectors.toList());
    }

    @Override
    public AjaxResult addQrcode(ContactWayVo contactWayVo, Long userId, Meta meta) {
        ContactWayInfo contactWay = contactWayVo.getContactWay();
        Map<String, String> users = contactWay.getUsers().stream()
                .collect(Collectors.toMap(ContactVo::getId, ContactVo::getName));
        String error = ContactWayApi.allowExternalOfUsers(users, meta);
        if (StrUtils.isNotEmpty(error)) {
            return AjaxResult.error(error);
        }

        // 编辑
        if (NumberUtils.isTrue(contactWay.getId())) {
            return this.updateContactWay(contactWayVo, meta);
        }
        // 新增
        WelcomeVo welcome = contactWayVo.getWelcome();
        contactWay.setState(meta.getTeamId() + "_LXW_" + RandomUtil.randomString(5));
        TxResponse response = ContactWayApi.addContactWay(contactWay, meta);
        JSONObject rsjson = response.getJson();
        if (!response.isSuccess()) {
            return AjaxResult.error(rsjson.toString());
        }
        contactWay.setConfigId(rsjson.getStr("config_id"));
        contactWay.setQrcodeUrl(rsjson.getStr("qr_code"));
        addWelcomeTemplate(contactWay, welcome, null, userId, meta.getTeamId());
        return AjaxResult.success();
    }


    @Override
    public AjaxResult updateContactWay(ContactWayVo contactWayVo, Meta meta) {
        WelcomeVo welcome = contactWayVo.getWelcome();
        ContactWayInfo contactWay = contactWayVo.getContactWay();
        ContactWayEntity old = selectById(contactWay.getId());
        if (Objects.isNull(old) || old.getIsDelete()) {
            return AjaxResult.error(ErrorConstants.NO_DATA);
        }
        contactWay.setConfigId(old.getConfigId());
        contactWay.setState(old.getState());
        TxResponse response = ContactWayApi.updateContactWay(contactWay, meta);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getJson().toString());
        }
        addWelcomeTemplate(contactWay, welcome, old.getWelcomeId(), null, meta.getTeamId());
        return AjaxResult.success();
    }

    @Transactional
    @Override
    public int insert(ContactWayEntity qrcode) {
        if (NumberUtils.isTrue(qrcode.getId())) {
            return update(qrcode.update());
        } else {
            return contactWayMapper.insert(qrcode);
        }
    }

    @Transactional
    @Override
    public int update(ContactWayEntity qrcode) {
        if (NumberUtils.isTrue(qrcode.getId())) {
            return contactWayMapper.updateById(qrcode);
        }
        return 0;
    }

    @Override
    public ContactWayEntity selectById(Long id) {
        return contactWayMapper.selectById(id);
    }

    @Override
    public AjaxResult delContactWayById(Long wayId, Meta meta) {
        ContactWayEntity old = selectById(wayId);
        if (Objects.isNull(old)) {
            return AjaxResult.success();
        }
        if (!old.getTeamId().equals(meta.getTeamId())) {
            return AjaxResult.noPermission();
        }
        TxResponse txResponse = ContactWayApi.delContactWay(old.getConfigId(), meta);
        if (txResponse.isSuccess()) {
            welcomeService.deleteById(old.getWelcomeId());
            deleteById(old.getId());
            return AjaxResult.success();
        }
        return AjaxResult.error(txResponse.getJson().toString());
    }

    @Transactional
    @Override
    public int deleteById(Long wayId) {
        return contactWayMapper.deleteById(wayId);
    }

    @Override
    public AjaxResult download(HttpServletRequest request, Long id, Long teamId) {
        ContactWayEntity way = contactWayMapper.selectOne(new QueryWrapper<ContactWayEntity>()
                .eq("team_id", teamId)
                .eq("id", id));
        if (Objects.isNull(way)) {
            return AjaxResult.error("联系我不存在或已删除");
        }
        String qrcodeUrl = way.getQrcodeUrl();
        // 没有开放平台，暂时不能 校验是否已是好友关系
        // 后续开通后，可通过unionId 获取关系，如果已经是好友，则可引导入群
//        if (way.getGuideJoin()) {
//            qrcodeUrl = QrCodeUtils.contactWayQrcode(teamId, id);
//        } else {
//            qrcodeUrl = way.getQrcodeUrl();
//        }
        return AjaxResult.success(Collections.singletonMap("url", qrcodeUrl));
    }

    @Override
    public QyWelcome findContactWayWelcome(String state, Meta meta) {
        if (StrUtils.isEmpty(state)) {
            return null;
        }
        String key = QywxKey.RedisKey.extContactWelcomeKey(meta.getTeamId(), state);
        QyWelcome welcome = redisCache.getCacheObject(key);
        if (Objects.nonNull(welcome)) {
            redisCache.expire(key, 5, TimeUnit.MINUTES);
            return welcome;
        }
        ContactWayEntity entity = contactWayMapper.selectOne(
                new QueryWrapper<ContactWayEntity>()
                        .select("welcome_id")
                        .eq("state", state)
                        .eq("team_id", meta.getTeamId())
        );
        if (NumberUtils.isTrue(entity.getWelcomeId())) {
            QyWelcome qyWelcome = QyWelcome.of(
                    welcomeService.selectById(entity.getWelcomeId()),
                    entity.getTags(),
                    entity.getRemark(),
                    meta);
            redisCache.setCacheObject(key, qyWelcome, 5, TimeUnit.MINUTES);
            return qyWelcome;
        }
        return null;
    }

    /**
     * @param contactWay 员工活码数据
     * @param welcome    欢迎语数据
     * @param welcomeId  更新欢迎语id
     * @param userId     用户id
     */
    private void addWelcomeTemplate(ContactWayInfo contactWay, WelcomeVo welcome,
                                    Long welcomeId, Long userId, Long teamId) {
        if (Objects.nonNull(welcome)) {
            if (NumberUtils.isTrue(contactWay.getId())) {
                String key = QywxKey.RedisKey.extContactWelcomeKey(teamId, contactWay.getState());
                redisCache.deleteObject(key);
            }
            QyWelcomeTemplate template = welcome.turnEntity(welcomeId);
            if (Objects.nonNull(template)) {
                welcomeService.insert(template);
                welcomeId = template.getId();
            }
        }
        ContactWayEntity contactWayEntity = contactWay.turnEntity(welcomeId, userId, teamId);
        insert(contactWayEntity);
    }
}
